/***************************************************************************
 *   Copyright (C) 2006 by Grzegorz Latarowski                             *
 *   g.latarowski@gmail.com                                                *
 *                                                                         *
 *   Project: AutoStop (kodowa nazwa do zmiany)                            *
 *                                                                         *
 ***************************************************************************/


#include "gtypes.h"


// ===========================================================================
//                                GHeader
// ===========================================================================


// ------------------------------ GHeader() ----------------------------------
GHeader::GHeader(QObject * parent) : QObject(parent)
{
        // ustawia magicka 
    _magicNumber = MAGIC_NUMBER;
        // oblicz rozmiar nagłówka i ustaw
    _headerSize = size();
        // wyzeruj rozmiar danych obiektu parenta
    _dataSize = -1;
        // ustaw typ obiektu parenta na -1 czyli nieznany
    _itemType = -1;
}
// ---------------------------------------------------------------------------


// ----------------------------- size() --------------------------------------
qint64 GHeader::size()
{
    qint64 size = 0;

    size += sizeof(_magicNumber);
    size += sizeof(_headerSize);
    size += sizeof(_dataSize);
    size += sizeof(_itemType);
    
    return size;
}
// ---------------------------------------------------------------------------


// --------------------------- operator << -----------------------------------
QDataStream & operator << (QDataStream & out, const GHeader &header)
{
        // zapisz wszystkie pola 
    out << header.magicNumber() << header.headerSize()
            << header.dataSize() << header.itemType();
    
        // zwróc strumień
    return out;
}
// ---------------------------------------------------------------------------


// --------------------------- operator >> -----------------------------------
QDataStream & operator >> (QDataStream & in, GHeader &header)
{
    quint8 magicNumber;
    qint64 headerSize;
    qint64 dataSize;
    qint32 itemType;

        // zaczytaj dane 
    in >> magicNumber >> headerSize >> dataSize >> itemType;

        // zapisz dane w headerze 
    header.setMagicNumber(magicNumber);
    header.setHeaderSize(headerSize);
    header.setDataSize(dataSize);
    header.setItemType(itemType);
    
        // zwróć strumień 
    return in;
}
// ---------------------------------------------------------------------------




// ===========================================================================
//                                  GEvent
// ===========================================================================


// -------------------------------- GEvent() ---------------------------------
GEvent::GEvent(QObject * parent) : QObject(parent)
{
    _dateTime = QDateTime::currentDateTime();
}
// ---------------------------------------------------------------------------


// ----------------------------- size() --------------------------------------
qint64 GEvent::size()
{
    qint64 size = 0;

        // dodaj rozmiar opisu po konwersji do
        // UTF-8 - domyślny standard kodowania znaków w aplikacji 
    size += _description.toUtf8().size();
        // zapisz date do bufora i zobacz jaki ma rozmiar
    QByteArray buffer;
    QDataStream bufferOut(&buffer, QIODevice::WriteOnly);
    bufferOut << _dateTime;
    size += buffer.size();
        // dodaj rozmiar obrazka
    size += _eventData.size();
    
    return size;
}
// ---------------------------------------------------------------------------
        

// ------------------------- GEvent::operator << -----------------------------
QByteArray & GEvent::operator << (QByteArray &eventData)
{
        // ustaw nowy obrazek
    setEventData(eventData);
        // zwróć strumień
    return eventData;
}
// ---------------------------------------------------------------------------


// ------------------------- GEvent::operator >> -----------------------------
QByteArray & GEvent::operator >> (QByteArray &eventData)
{
        // zaczytaj obrazek do picture
    eventData = _eventData;
        //zwróć strumień
    return eventData;
}
// ---------------------------------------------------------------------------


// --------------------------- operator << -----------------------------------
QDataStream & operator << (QDataStream & out, const GEvent &event)
{
        // oblicz rozmiar danych w obiekcie picture
    QByteArray eventBuffer;
    QDataStream bufferOut(&eventBuffer, QIODevice::WriteOnly);
    bufferOut << event.description() << event.dateTime()
            << event.eventData();

        // ustaw nagłówek 
    GHeader header;
    header.setDataSize(eventBuffer.size());
    header.setItemType(0x01);
    
        // zapisz pola do strumienia
    out << header << eventBuffer;
    
        // zwróc strumień
    return out;
}
// ---------------------------------------------------------------------------


// --------------------------- operator >> -----------------------------------
QDataStream & operator >> (QDataStream & in, GEvent &event)
{
        // zaczytaj nagłówek
    GHeader header;
        // zapisz domyślny rozmiar nagłówka
    qint64 nativeHeaderSize = header.headerSize();
        // zaczytaj nagłówek 
    in >> header;
        // zaczytaj rozmiar nagłówka czytanego obiektu 
    qint64 headerSize = header.headerSize();
        // jeśli nagłówek jest nowszego typu to porzuć resztę danych
    if((headerSize - nativeHeaderSize) > 0) {
        in.skipRawData(headerSize - nativeHeaderSize);
    }

        // sprawdź ile danych czeka do przeczytania 
    qint64 dataSize = header.dataSize();
        // utwórz bufor na spodziewane dane i zaczytaj je 
    QByteArray incomingData(dataSize, 0);
    in.readRawData(incomingData.data(), dataSize);

    QString description;
    QDateTime dateTime;
    QByteArray eventData;

        // zaczytaj dane z bufora
    QDataStream incomingDataStream(&incomingData, QIODevice::ReadOnly);
    incomingDataStream >> description >> dateTime >> eventData;

        // zapisz pola do obiektu 
    event.setDescription(description);
    event.setDateTime(dateTime);
    event.setEventData(eventData);
    
        // zwróć strumień 
    return in;
}
// ---------------------------------------------------------------------------







